﻿#include "SingleInstanceApplication.h"
#include <QFile>
#include <QDir>
#include <QProcess>

#ifdef Q_OS_WIN
#include <Windows.h>
#endif

#define INST_NAME "TlvTool_SingleInstance"
#define SHOW_CMD  "show"

SingleInstanceApplication::SingleInstanceApplication(int &argc, char **argv)
    : QApplication(argc, argv)
    , m_serverName(INST_NAME)
{
    // 尝试连接已存在实例
    QLocalSocket socket;
    socket.connectToServer(m_serverName);

    if (socket.waitForConnected(100)) {
        // 已有实例存在
        socket.write(SHOW_CMD);
        socket.flush();
        socket.waitForBytesWritten(100);
        m_isPrimary = false;
        return;
    }

    // 清除上次异常退出遗留的 socket 文件
    QFile::remove(QDir::temp().filePath(m_serverName));

    // 创建本地服务器，成为主实例
    m_server = new QLocalServer(this);
    if (m_server->listen(m_serverName)) {
        m_isPrimary = true;
        connect(m_server, &QLocalServer::newConnection, this, &SingleInstanceApplication::handleNewConnection);
    }
}

void SingleInstanceApplication::setMainWindow(QWidget *window)
{
    m_mainWindow = window;
    connect(this, &SingleInstanceApplication::requestShowUp, this, &SingleInstanceApplication::activeMainWindow);
}

void SingleInstanceApplication::restart(const QStringList &args)
{
    // 先关闭 实例互斥，防止重启的新实例被杀死：
    if (m_server) {
        m_server->close();
        QFile::remove(QDir::temp().filePath(m_serverName));
        delete m_server;
        m_server = nullptr;
    }

    // 重启：
    QStringList restartArgs;

    if (args.isEmpty()) {
        // 使用当前参数
        restartArgs = QCoreApplication::arguments();
        restartArgs.removeFirst(); // 移除程序路径
    } else {
        // 使用新参数
        restartArgs = args;
    }
    QString program = QCoreApplication::applicationFilePath();

    // 启动新进程
    QProcess::startDetached(program, restartArgs);

    // 退出当前进程
    qApp->quit();

}

void SingleInstanceApplication::handleNewConnection()
{
    if (!m_server) return;

    QLocalSocket *client = m_server->nextPendingConnection();
    if (!client) return;

    connect(client, &QLocalSocket::readyRead, [this, client]() {
        QByteArray data = client->readAll();
        if (data == SHOW_CMD) {
            emit requestShowUp();
        }
        client->disconnectFromServer();
    });
}

void SingleInstanceApplication::activeMainWindow()
{
    if (!m_mainWindow) return;
    // 确保窗口可见
    m_mainWindow->show();
    m_mainWindow->raise();
    m_mainWindow->activateWindow();

#ifdef Q_OS_WIN
    // 强制前置到最前
    HWND hwnd = reinterpret_cast<HWND>(m_mainWindow->winId());
    AllowSetForegroundWindow(DWORD(-1));  // 允许任意进程设置前台
    SetForegroundWindow(hwnd);

    // 修复不是按照原大小显示的问题：
    if (m_mainWindow->isMaximized()) ShowWindow(hwnd, SW_SHOWMAXIMIZED);
    else ShowWindow(hwnd, SW_SHOWDEFAULT);
#endif
}
